package com.aliang.shopping.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.aliang.shopping.common.PageResult;
import com.aliang.shopping.common.Result;
import com.aliang.shopping.common.ResultCodeEnum;
import com.aliang.shopping.config.OssConfig;
import com.aliang.shopping.contact.BasicConstant;
import com.aliang.shopping.contact.ResultMsgContact;
import com.aliang.shopping.contact.SqlColumnConstant;
import com.aliang.shopping.exception.DataException;
import com.aliang.shopping.exception.ServiceException;
import com.aliang.shopping.log.annotation.OperateLog;
import com.aliang.shopping.log.enums.OperateType;
import com.aliang.shopping.model.converter.BusinessConverter;
import com.aliang.shopping.model.dto.business.BusinessInsertDTO;
import com.aliang.shopping.model.dto.business.BusinessSearchDTO;
import com.aliang.shopping.model.dto.business.BusinessUpdateDTO;
import com.aliang.shopping.model.dto.business.BusinessUpdateStatusDTO;
import com.aliang.shopping.model.dto.common.UpdatePasswordDTO;
import com.aliang.shopping.model.dto.common.UpdateStatusDTO;
import com.aliang.shopping.model.enums.BusinessStatusType;
import com.aliang.shopping.model.po.Business;
import com.aliang.shopping.model.vo.business.BusinessExportVO;
import com.aliang.shopping.model.vo.business.BusinessVO;
import com.aliang.shopping.security.PreventRepeatSubmit;
import com.aliang.shopping.service.BusinessService;
import com.aliang.shopping.service.UserInfoService;
import com.aliang.shopping.util.InputDataUtil;
import com.aliang.shopping.util.MailUtil;
import com.aliang.shopping.util.PasswordUtil;
import com.aliang.shopping.util.excel.ExcelUtils;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Objects;

@RestController
@RequestMapping("/business")
@AllArgsConstructor
public class BusinessController {

    private final BusinessService businessService;
    private final BusinessConverter businessConverter;
    private final ExcelUtils excelUtils;
    private final MailUtil mailUtil;
    private final OssConfig ossConfig;
    private final UserInfoService userInfoService;


    /**
     * 商家信息插入
     */
    @PostMapping("/insert")
    @ApiOperation("商家信息插入")
    @PreventRepeatSubmit
    @OperateLog(title = "商家信息插入", type = OperateType.INSERT)
    public Result<String> insertBusiness(@RequestBody BusinessInsertDTO insertDTO) {
        //必要字段非空校验
        if (BeanUtil.hasNullField(insertDTO) || StrUtil.hasBlank(insertDTO.getUsername(), insertDTO.getPassword())) {
            throw new DataException(ResultCodeEnum.DATA_LACK);
        }
        // 密码长度校验
        if (StrUtil.length(insertDTO.getPassword()) < 8) {
            throw new DataException(ResultCodeEnum.PASSWORD_LENGTH_ERR);
        }

        // 判断账号唯一
        int count = businessService.count(new QueryWrapper<Business>().eq("username", insertDTO.getUsername()));
        if (count > 0) {
            throw new ServiceException(ResultCodeEnum.USERNAME_IS_EXIT);
        }
        //电话,邮箱不为空，需要验证唯一性
        if (StrUtil.isNotBlank(insertDTO.getPhone())) {
            this.userInfoService.checkPhoneUnique(insertDTO.getPhone());
        }
        if (StrUtil.isNotBlank(insertDTO.getEmail())) {
            this.userInfoService.checkEmailUnique(insertDTO.getEmail());
        }
        //如果店铺名未设置，设置为账号
        if (StrUtil.isBlank(insertDTO.getStoreName())) {
            insertDTO.setStoreName(insertDTO.getUsername());
        }
        // 密码加密
        insertDTO.setPassword(PasswordUtil.encrypt(insertDTO.getPassword()));
        // 如果有头像路径，需要截取
        if (StrUtil.isNotBlank(insertDTO.getAvatar())) {
            insertDTO.setAvatar(StrUtil.subAfter(insertDTO.getAvatar(), ossConfig.getUrl(), false));
        }
        //如果有资质证明，需要替换
        if (StrUtil.isNotBlank(insertDTO.getQualification())) {
            insertDTO.setQualification(StrUtil.replace(insertDTO.getQualification(), ossConfig.getUrl(), BasicConstant.REPLACE_IMAGE));
        }
        //转换数据
        Business business = this.businessConverter.toPoByInsertDTO(insertDTO);
        this.businessService.save(business);
        return Result.ok(ResultMsgContact.REGISTER_SUCCESS);
    }

    /**
     * 商家信息删除
     */
    @DeleteMapping("/del")
    @ApiOperation("商家信息删除")
    @PreventRepeatSubmit
    @OperateLog(title = "商家信息删除", type = OperateType.DELETE)
    public Result<String> delBusiness(@RequestBody List<Long> ids) {
        this.businessService.removeByIds(ids);
        return Result.ok(ResultMsgContact.DELETE_SUCCESS);
    }

    /**
     * 商家信息更改
     */
    @PutMapping("/update")
    @ApiOperation("商家信息更改")
    @PreventRepeatSubmit
    @OperateLog(title = "商家信息更改", type = OperateType.UPDATE)
    public Result<String> updateBusiness(@RequestBody BusinessUpdateDTO updateDTO) {
        //必要字段校验
        if (ObjectUtil.isNull(updateDTO.getId())) {
            throw new DataException(ResultCodeEnum.DATA_LACK);
        }
        // 如果有头像路径，需要截取
        if (StrUtil.isNotBlank(updateDTO.getAvatar())) {
            updateDTO.setAvatar(StrUtil.subAfter(updateDTO.getAvatar(), ossConfig.getUrl(), false));
        }
        //如果有资质证明，需要替换
        if (StrUtil.isNotBlank(updateDTO.getQualification())) {
            updateDTO.setQualification(StrUtil.replace(updateDTO.getQualification(), ossConfig.getUrl(), BasicConstant.REPLACE_IMAGE));
        }
        //转换数据
        Business business = this.businessConverter.toPoByUpdateDTO(updateDTO);
        this.businessService.updateById(business);
        return Result.ok(ResultMsgContact.UPDATE_SUCCESS);
    }

    /**
     * 商家账号状态更改
     *
     * @param updateDTO
     */
    @PutMapping("/update_static")
    @ApiOperation("商家账号状态更改")
    @PreventRepeatSubmit
    @OperateLog(title = "商家账号状态更改", type = OperateType.UPDATE)
    public Result<String> updateBusinessAccountStatic(@RequestBody UpdateStatusDTO updateDTO) {
        //必要字段校验
        if (BeanUtil.isEmpty(updateDTO)) {
            throw new DataException(ResultCodeEnum.DATA_LACK);
        }
        // 状态数字合法性校验
        if (!InputDataUtil.numIsOK(updateDTO.getStatus())) {
            throw new DataException(ResultCodeEnum.TYPE_NUM_ERR);
        }
        //转换数据
        Business business = this.businessConverter.toPoByUpdateStaticDTO(updateDTO);
        this.businessService.updateById(business);
        return Result.ok(ResultMsgContact.UPDATE_STATUS_SUCCESS);
    }

    /**
     * 店家状态更改
     *
     * @param updateDTO
     */
    @PutMapping("/update_business_static")
    @ApiOperation("店家状态更改")
    @PreventRepeatSubmit(expireTime = 60)
    @OperateLog(title = "店家状态更改", type = OperateType.UPDATE)
    public Result<String> updateBusinessStatic(@RequestBody BusinessUpdateStatusDTO updateDTO) {
        //必要字段校验
        if (BeanUtil.isEmpty(updateDTO)) {
            throw new DataException(ResultCodeEnum.DATA_LACK);
        }
        // 状态数字合法性校验
        if (!InputDataUtil.numIsOK(updateDTO.getStatus(), BusinessStatusType.DISABLE.getCode(), BusinessStatusType.NORMAL.getCode())) {
            throw new DataException(ResultCodeEnum.TYPE_NUM_ERR);
        }
        //转换数据
        Business business = this.businessConverter.toPoByUpdateBusinessStaticDTO(updateDTO);
        this.businessService.updateById(business);
        //获取邮箱
        Business one = this.businessService.getOne(new QueryWrapper<Business>()
                .select(SqlColumnConstant.EMAIL)
                .eq(SqlColumnConstant.ID, updateDTO.getId())
                .eq(SqlColumnConstant.STATUS, SqlColumnConstant.STATUS_OK));
        if (StrUtil.isBlank(one.getEmail())) {
            throw new ServiceException(ResultCodeEnum.EMAIL_NOT_EXIT);
        }
        //获取审核结果
        String msg;
        //审核失败。发送邮箱提醒
        if (Objects.equals(BusinessStatusType.UNDER_REVIEW_BANK.getCode(), updateDTO.getStatus())) {
            //判断是否以句号结尾
            String failMsg = updateDTO.getFailMsg();
            if (failMsg.charAt(failMsg.length() - 1) != '。' || failMsg.charAt(failMsg.length() - 1) != '.')
                failMsg += '。';
            msg = ResultMsgContact.VALIDATE_FAIL + failMsg + ResultMsgContact.VALIDATE_FAIL_SUFFIX;
        } else {
            msg = ResultMsgContact.VALIDATE_SUCCESS;
        }
        //发送通知邮箱
        mailUtil.sendValidateFailEmail(one.getEmail(), msg);
        return Result.ok(ResultMsgContact.UPDATE_BUSINESS_STATUS_SUCCESS);
    }

    /**
     * 商家信息个人密码修改
     */
    @PutMapping("/update_pwd")
    @ApiOperation("商家信息个人密码修改")
    @PreventRepeatSubmit
    @OperateLog(title = "商家信息个人密码修改", type = OperateType.UPDATE)
    public Result<String> updateBusinessSelfPwd(@RequestBody UpdatePasswordDTO updateDTO) {
        //校验密码
        PasswordUtil.validate(updateDTO);
        //判断账号是否一致
        Business business = this.businessService.getOne(new QueryWrapper<Business>().select("password").eq("id", updateDTO.getId()));
        if (ObjectUtil.isNull(business)) {
            throw new ServiceException(ResultCodeEnum.USERNAME_IS_NOT_EXIT);
        }
        //判断输入的旧密码与密码是否一致
        if (PasswordUtil.isNotEqual(business.getPassword(), updateDTO.getOldPassword())) {
            throw new DataException(ResultCodeEnum.OLD_PASSWORD_NOT_WITH);
        }
        //转换数据
        Business save = this.businessConverter.toPoByUpdatePasswordDTO(updateDTO);
        //保存数据
        this.businessService.updateById(save);
        return Result.ok(ResultMsgContact.UPDATE_PWD_SUCCESS);
    }


    /**
     * 商家信息分页搜索
     */
    @GetMapping("/getPage")
    @ApiOperation("商家信息分页搜索")
    public Result<PageResult<BusinessVO>> queryBusinessPage(BusinessSearchDTO pageDTO) {
        //必要字段校验
        if (ObjectUtil.hasNull(pageDTO.getPageSize(), pageDTO.getPageNum())) {
            throw new DataException(ResultCodeEnum.DATA_LACK);
        }
        //查询数据
        PageResult<BusinessVO> result = this.businessService.selectPage(pageDTO);
        return Result.ok(result);
    }

    /**
     * 根据Id获取商家信息
     */
    @GetMapping("/getUserInfo/{id}")
    @ApiOperation("根据Id获取商家信息")
    public Result<BusinessVO> getBusinessInfoById(@PathVariable Long id) {
        Business business = this.businessService.getById(id);
        if (Objects.isNull(business)) {
            throw new ServiceException(ResultCodeEnum.USERNAME_IS_NOT_EXIT);
        }
        //转换数据
        BusinessVO vo = this.businessConverter.toVO(business);
        // 如果有头像路径，设置完整路径
        if (StrUtil.isNotBlank(vo.getAvatar())) {
            vo.setAvatar(ossConfig.getUrl() + vo.getAvatar());
        }
        //如果有资质证明，需要替换
        if (StrUtil.isNotBlank(vo.getQualification())) {
            // 标记设置为完整路径
            vo.setQualification(StrUtil.replace(vo.getQualification(), BasicConstant.REPLACE_IMAGE, ossConfig.getUrl()));
        }
        return Result.ok(vo);
    }

    /**
     * 商家信息导出
     */
    @ApiOperation("导出商家信息信息")
    @GetMapping("/export")
    @PreventRepeatSubmit
    @OperateLog(title = "导出商家信息信息", type = OperateType.EXPORT)
    public void exportBusiness(BusinessSearchDTO pageDTO, HttpServletResponse response) throws IOException {
        String fileName = "商家信息列表.xlsx";
        // 设置请求头
        this.excelUtils.setHeader(response, fileName);
        List<BusinessExportVO> exportUserList = this.businessService.getExportList(pageDTO);
        //查询数据
        EasyExcel.write(response.getOutputStream(), BusinessExportVO.class).sheet("商家信息列表")
                .doWrite(exportUserList);
    }
}
